package com.woniuxy.controller;



import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.config.AlipayConfig;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.woniuxy.commons.exception.CartException;
import com.woniuxy.commons.exception.code.CartExceptionCode;
import com.woniuxy.commons.model.Result;
import com.woniuxy.commons.utils.CommonsUtil;
import com.woniuxy.controller.form.*;
import com.woniuxy.dao.model.CartInfo;
import com.woniuxy.dao.model.CustomerInfo;
import com.woniuxy.dao.model.FoodVariety;
import com.woniuxy.controller.form.AddCartForm;
import com.woniuxy.controller.form.DelCartForm;
import com.woniuxy.dao.model.StoreInfo;
import com.woniuxy.service.*;
import com.woniuxy.service.CartInfoService;
import com.woniuxy.service.StoreInfoService;
import com.woniuxy.service.dto.AllCartListDto;
import com.woniuxy.service.dto.CartAllCategoryDto;
import com.woniuxy.service.dto.UserDetailsDto;
import io.swagger.annotations.*;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author psy
 * @since 2022-06-28
 */
@RestController
@RequestMapping("/cartInfo")
@Api(tags="购物车接口")
public class CartInfoController {
    @Resource
    private StoreInfoService storeInfoService;
    @Resource
    private CartInfoService cartInfoService;
    @Resource
    private DietOrderService dietOrderService;
    @Resource
    private FoodVarietyService foodVarietyService;
    @Resource
    private DietOrderFoodService dietOrderFoodService;
    @Resource
    private DietOrderLogService dietOrderLogService;
    @Resource
    private RedisTemplate<String,String> sot;
    @Resource
    private RedisTemplate<String,Object> soot;

    /*
    * 初始化购物车（查询）（限制用户只能选择两家商家的菜品！！）
    * @param customerId用户ID
    *@result 购物车商品列表(从redis中调取)
    * */
    @GetMapping("/loadcart")
    @ApiOperation("加载购物车信息")
    public Result loadCart() throws JsonProcessingException {
        UserDetailsDto userDetailsDto=(UserDetailsDto)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Long customerId=userDetailsDto.getId();
        System.out.println(customerId);
        if(null!=sot.opsForValue().get(customerId+"")){
            String o = (String)sot.opsForValue().get(customerId + "");
            ArrayList<AllCartListDto> allCartListDtos1 = (ArrayList<AllCartListDto>) JSONObject.parseArray(o, AllCartListDto.class);
            System.out.println(allCartListDtos1);
            //提取商家名称属性
            List<String> names = allCartListDtos1.stream().distinct().map(p -> p.getStoreName()).collect(Collectors.toList());
            //商家名称去重并加入到list中
            List<String> collect = names.stream().distinct().collect(Collectors.toList());
            //最终返回的集合（根据商家名称分类）
            ArrayList<CartAllCategoryDto> cartAllCategoryDtos=new ArrayList<>();
            for (int i = 0; i < collect.size(); i++) {
                CartAllCategoryDto c=new CartAllCategoryDto();
                //创建新的每一个餐厅的购物车信息
                double dphPrice=0;
                double packingPrice=0;
                double total=0;
                int per=0;
                long storeId=0;
                ArrayList<AllCartListDto> rest=new ArrayList<AllCartListDto>();
                for (AllCartListDto allCartListDto : allCartListDtos1) {
                    if(collect.get(i).equals(allCartListDto.getStoreName())){
                        rest.add(allCartListDto);
                        dphPrice=allCartListDto.getDphPrice();
                        packingPrice=allCartListDto.getPackingPrice();
                        total+=allCartListDto.getPrice();
                        per+=allCartListDto.getNum();
                        storeId=allCartListDto.getStoreId();
                    }
                }
                c.setStoreId(storeId);
                c.setPer(per);
                c.setTotal(total+dphPrice+packingPrice);
                c.setDphPrice(dphPrice);
                c.setPackingPrice(packingPrice);
                c.setStoreName(collect.get(i));
                c.setRest(rest);
                cartAllCategoryDtos.add(c);
            }
            return Result.success(200,"加载购物车成功",cartAllCategoryDtos);
        }else{
            ArrayList<AllCartListDto> allCartListDtos1 = cartInfoService.getAllCartsByCustomerId(customerId);
            //提取商家名称属性
            List<String> names = allCartListDtos1.stream().distinct().map(p -> p.getStoreName()).collect(Collectors.toList());
            //商家名称去重并加入到list中
            List<String> collect = names.stream().distinct().collect(Collectors.toList());
            //最终返回的集合（根据商家名称分类）
            ArrayList<CartAllCategoryDto> cartAllCategoryDtos=new ArrayList<>();
            for (int i = 0; i < collect.size(); i++) {
                CartAllCategoryDto c=new CartAllCategoryDto();
                //创建新的每一个餐厅的购物车信息
                double dphPrice=0;
                double packingPrice=0;
                double total=0;
                int per=0;
                long storeId=0;
                ArrayList<AllCartListDto> rest=new ArrayList<AllCartListDto>();
                for (AllCartListDto allCartListDto : allCartListDtos1) {
                    if(collect.get(i).equals(allCartListDto.getStoreName())){
                        dphPrice=allCartListDto.getDphPrice();
                        packingPrice=allCartListDto.getPackingPrice();
                        rest.add(allCartListDto);
                        total+=allCartListDto.getPrice();
                        per+=allCartListDto.getNum();
                        storeId=allCartListDto.getStoreId();
                    }
                }
                c.setStoreId(storeId);
                c.setPer(per);
                c.setTotal(total+dphPrice+packingPrice);
                c.setDphPrice(dphPrice);
                c.setPackingPrice(packingPrice);
                c.setStoreName(collect.get(i));
                c.setRest(rest);
                cartAllCategoryDtos.add(c);
            }
            return Result.success(200,"加载购物车成功",cartAllCategoryDtos);
        }

    }

    /**
     * 根据商家加载购物车信息(用于前端指定餐厅界面的购物车展示)
     * @param storeName 接收前端传递的商家名称
     * @return
     */
    @GetMapping("/loadcartbystore")
    @ApiOperation("根据商家加载购物车信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "storeName",value = "商家名称")
    })
    public Result loadStoreByStore(String storeName){
        ArrayList<AllCartListDto> allCartListDtos = cartInfoService.loadStoreByStore(storeName);
        CartAllCategoryDto c=new CartAllCategoryDto();
        double dphPrice=0;
        double packingPrice=0;
        double total=0;
        int per=0;
        long storeId=0;
        for (AllCartListDto allCartListDto : allCartListDtos) {
                dphPrice=allCartListDto.getDphPrice();
                packingPrice=allCartListDto.getPackingPrice();
                total+=allCartListDto.getPrice();
                per+=allCartListDto.getNum();
                storeId=allCartListDto.getStoreId();

        }
        c.setStoreId(storeId);
        c.setPer(per);
        c.setTotal(total+dphPrice+packingPrice);
        c.setDphPrice(dphPrice);
        c.setPackingPrice(packingPrice);
        c.setStoreName(storeName);
        c.setRest(allCartListDtos);

        return Result.success(200,"加载对应商家的购物车成功",c);
    }
    /*
    * 点击商品添加购物车（对象接收）
    * @param addressInfo 接收前端传过来的商品数据
    *@result
    * */
    @PostMapping("/addcart")
    @ApiOperation("添加购物车")
    public Result addCart(@RequestBody AddCartForm addCartForm) throws JsonProcessingException {
        System.out.println(addCartForm);
        AllCartListDto cart = cartInfoService.findCart(addCartForm.getFoodName());
        if(null==cart){
            UserDetailsDto userDetailsDto=(UserDetailsDto)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            addCartForm.setCustomerId(userDetailsDto.getId());
            String storeName = addCartForm.getStoreName();
            Long storeId = addCartForm.getStoreId();
            String store = (String)sot.opsForValue().get("store:"+storeId);
            System.out.println(store);
            StoreInfo storeInfo = JSON.parseObject(store,StoreInfo.class);
            Double packingPrice = storeInfo.getPackingPrice();
            Double dphPrice = storeInfo.getDphPrice();
            addCartForm.setDphPrice(dphPrice);
            addCartForm.setPackingPrice(packingPrice);
            Boolean aBoolean = cartInfoService.addCart(addCartForm);
            return Result.success(200,"添加购物车成功",null);
        }else{
            return Result.success(200,"添加购物车成功",null);
        }

    }

    /**
     * 删除购物车单项
     * @param foodName 接收前端传递的商品名称
     * @return
     */
    @DeleteMapping("/delCart")
    @ApiOperation("删除购物车单品")
    @ApiImplicitParams(
            {
                    @ApiImplicitParam(name="foodName",value="接收前端传递的商品名称")
            }
    )
    public Result delCart(String foodName) throws JsonProcessingException {
        DelCartForm delCartForm=new DelCartForm();
        delCartForm.setFoodName(foodName);
        UserDetailsDto userDetailsDto=(UserDetailsDto)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        delCartForm.setCustomerId(userDetailsDto.getId());
        Boolean aBoolean = cartInfoService.delCart(delCartForm);
        return Result.success(200,"删除成功",null);
    }

    /**
     * 下单删除购物车
     * @param storeName 接收前端传过来的商铺名称（和后端的用户ID结合一起删除对应的购物车商品）
     * @return
     */
    @DeleteMapping("/delcarts")
    @ApiOperation("下单时删除购物车")
    @ApiImplicitParams(
            {
                    @ApiImplicitParam(name="storeName",value="接收前端传过来的商家名称")
            }
    )
    public Result delCarts(String storeName) throws JsonProcessingException {
        UserDetailsDto userDetailsDto=(UserDetailsDto)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Long id = userDetailsDto.getId();
        Boolean aBoolean = cartInfoService.delCarts(id, storeName);
        return Result.success(200,"删除成功",null);
    }


    @PostMapping("/pay")
    @ApiOperation("付款流程(支付宝)和生成订单")
    public String pay(@RequestBody PayAddressSumForm payForm) {
        PayAddressForm payAddressForm = payForm.getPayAddressForm();
        if(null!=payAddressForm.getOrderNum()&&!"null".equals(payAddressForm.getOrderNum())){
            //已有订单进行付款
            String orderNum=payAddressForm.getOrderNum();
            double total=payAddressForm.getTotal();
            String price=total+"";
            UserDetailsDto userDetailsDto = (UserDetailsDto) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            String username = userDetailsDto.getUsername();
            String ordername=username+"的订单";
            //获得初始化的AlipayClient
            AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_private_key, "json", AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type);

            //设置请求参数
            AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
            alipayRequest.setReturnUrl(AlipayConfig.return_url);
            alipayRequest.setNotifyUrl(AlipayConfig.notify_url);

            //商户订单号，商户网站订单系统中唯一订单号，必填
            String out_trade_no = new String(orderNum);
            System.out.println(out_trade_no);
            //付款金额，必填
            String total_amount = new String(price);
            //订单名称，必填
            String subject = new String(ordername);
            //商品描述，可空
            String body = new String();

            alipayRequest.setBizContent("{\"out_trade_no\":\"" + out_trade_no + "\","
                    + "\"total_amount\":\"" + total_amount + "\","
                    + "\"subject\":\"" + subject + "\","
                    + "\"body\":\"" + body + "\","
                    + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");

            //若想给BizContent增加其他可选请求参数，以增加自定义超时时间参数timeout_express来举例说明
            //alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
            //		+ "\"total_amount\":\""+ total_amount +"\","
            //		+ "\"subject\":\""+ subject +"\","
            //		+ "\"body\":\""+ body +"\","
            //		+ "\"timeout_express\":\"10m\","
            //		+ "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
            //请求参数可查阅【电脑网站支付的API文档-alipay.trade.page.pay-请求参数】章节

            //请求
            String result = null;
            try {
                result = alipayClient.pageExecute(alipayRequest).getBody();
            } catch (AlipayApiException e) {
                e.printStackTrace();
            }

            //输出
            System.out.println(result);
            return result;
        }
        //验证是否满足起送价

        System.out.println(payAddressForm);
        Long storeId = payAddressForm.getStoreId();
        System.out.println(storeId);
        StoreInfo byId = storeInfoService.getById(storeId);
        Integer initiatePrice = byId.getInitiatePrice();
        if(payAddressForm.getTotal()<initiatePrice){
            return "不满起送价";
        }

        System.out.println(payForm);
        String storeName = payAddressForm.getStoreName();
        Long id=payAddressForm.getStoreId();
        //总价
        double total = payAddressForm.getTotal();

        List<PayForm> payForm2 = payForm.getPayForm();
        String price = total + "";
        //订单编号
        String orderNum = UUID.randomUUID().toString();
        //订单状态
        Integer state = 0;
        //下单时间
        String orderDate = CommonsUtil.getOrderCreateTime();
        UserDetailsDto userDetailsDto = (UserDetailsDto) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        //订餐人
        String username = userDetailsDto.getUsername();
        //订餐人ID
        Long customerId=userDetailsDto.getId();
        //订餐人电话
        String phone = userDetailsDto.getPhone();
        String ordername = username + "的订单";
        CreateOrderForm createOrderForm = new CreateOrderForm();
        createOrderForm.setCustomerId(customerId);
        createOrderForm.setAddress(payAddressForm.getAddressDetails());
        createOrderForm.setOrderDate(orderDate);
        createOrderForm.setOrderNum(orderNum);
        createOrderForm.setOrderPhone(phone);
        createOrderForm.setOrderUser(username);
        createOrderForm.setPrice(total);
        createOrderForm.setReceiveName(payAddressForm.getAddressName());
        createOrderForm.setRemarks(payAddressForm.getRemarks());
        createOrderForm.setState(state);
        createOrderForm.setStoreId(id);
        createOrderForm.setStoreName(payAddressForm.getStoreName());
        //新增订单
        boolean b = dietOrderService.addOrder(createOrderForm);
        System.out.println("新增订单成功");
        //新增订单菜品表
        List<PayForm> payForm1 = payForm.getPayForm();
        for (PayForm form : payForm1) {
            String foodName = form.getFoodName();
//            Long id1 = form.getFoodId();
            CreateOrderFoodForm createOrderFoodForm = new CreateOrderFoodForm();
            createOrderFoodForm.setCount(form.getNum());
//            createOrderFoodForm.setFoodId(id1);
            createOrderFoodForm.setFoodName(foodName);
            createOrderFoodForm.setOrderNum(orderNum);
            createOrderFoodForm.setPrice(form.getPrice());
            boolean b1 = dietOrderFoodService.addOrderFood(createOrderFoodForm);
        }
        System.out.println("新增订单菜品表成功");
        //新增订单日志表
        OrderLogForm orderLogForm = new OrderLogForm();
        orderLogForm.setOrderNum(orderNum);
        orderLogForm.setOrderState(0);
        orderLogForm.setOperContent("下单付款");
        orderLogForm.setOperDate(orderDate);
        orderLogForm.setOperReason("付款");
        orderLogForm.setOperName("下单并点击付款");
        orderLogForm.setOperUser(username);
        Boolean aBoolean = dietOrderLogService.addOrderLog(orderLogForm);
        System.out.println("新增订单日志成功");
        System.out.println("==================================");


        //获得初始化的AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_private_key, "json", AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type);

        //设置请求参数
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        alipayRequest.setReturnUrl(AlipayConfig.return_url);
        alipayRequest.setNotifyUrl(AlipayConfig.notify_url);

        //商户订单号，商户网站订单系统中唯一订单号，必填
        String out_trade_no = new String(orderNum);
        System.out.println(out_trade_no);
        //付款金额，必填
        String total_amount = new String(price);
        //订单名称，必填
        String subject = new String(ordername);
        //商品描述，可空
        String body = new String();

        alipayRequest.setBizContent("{\"out_trade_no\":\"" + out_trade_no + "\","
                + "\"total_amount\":\"" + total_amount + "\","
                + "\"subject\":\"" + subject + "\","
                + "\"body\":\"" + body + "\","
                + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");

        //若想给BizContent增加其他可选请求参数，以增加自定义超时时间参数timeout_express来举例说明
        //alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
        //		+ "\"total_amount\":\""+ total_amount +"\","
        //		+ "\"subject\":\""+ subject +"\","
        //		+ "\"body\":\""+ body +"\","
        //		+ "\"timeout_express\":\"10m\","
        //		+ "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
        //请求参数可查阅【电脑网站支付的API文档-alipay.trade.page.pay-请求参数】章节

        //请求
        String result = null;
        try {
            result = alipayClient.pageExecute(alipayRequest).getBody();
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }

        //输出
        System.out.println(result);
        return result;
    }

}

